# -*- coding: utf-8 -*-
"""
Nome do módulo: estatisticas.py
autores: Pedro Caixinha Nº4437 e Pedro Lopes Nº9850
data: 30/10/2013
Obs.: Este módulo contém funções que permitem gerar estatisticas relativamente aos dados que constam na base de dados, no seguinte âmbito:
      - Informação sobre o número de alunos colocados por instituição;
      - Informação sobre o número de vagas por colocar por instituição;
      - Informação relativa à percentagem de alunos colocados por instituição, em relação a todos os alunos colocados na 1ª fase de candidaturas ao ensino superio público português;
      - Informação sobre o número de alunos colocados por distrito;
      - Informação sobre o número de vagas por colocar por distrito;
      - Informação relativa à permilagem de alunos colocados por distrito.
"""
import os
import bd
import util
from sqlalchemy import func
import numpy as np
import matplotlib.pyplot as plt
import decimal
import collections

class Estatisticas:
    """
    Classe Estatisticas.
    """
    def colocacoes_instituicao(self, session, instituicao):
        """
        Função que gera estatísticas sobre o número de alunos colocados por instituição.

            return:
                info -- string com informação resultante das estatísticas.
                
            Argumentos:
                sessio -- objecto que permite efectuar a ligação a base de dados.
                instituicao -- nome da instituição acerca da qual serão geradas as estatísticas.
        """
        dados_escola = {}
        n_escolas = 0
        total_colocados = 0
        total_vagas_sobrantes = 0
    
        q_res = session.query(bd.Escola.nome, func.sum(bd.EscolaCurso.n_colocados), func.sum(bd.EscolaCurso.vagas_sobrantes)).filter(bd.Instituicao.nome == instituicao).filter(bd.Escola.id_instituicao == bd.Instituicao.id).filter(bd.EscolaCurso.id_escola == bd.Escola.id).group_by(bd.Escola.nome).all()
    
        for res in q_res:
            n_escolas += 1
            dados_escola[n_escolas] = (res[0], res[1], res[2])
            total_colocados += res[1]
            total_vagas_sobrantes += res[2]

        n_vagas = total_colocados + total_vagas_sobrantes    
        perc_colocacoes = (float(total_colocados) / n_vagas) * 100
        
        dados_escola = collections.OrderedDict(sorted(dados_escola.items()))

        info = instituicao + u"\n\nAno Lectivo de 2013/2014 - 1ª Fase das Candidaturas de Acesso ao Ensino Superior Público Nacional\n\n\tPercentagem de colocações: " + str("%.2f" %perc_colocacoes + "%") + "\n\tTotal de alunos colocados: " + str(total_colocados) + "\n\tTotal de vagas sobrantes: " + str(total_vagas_sobrantes) + "\n"

        for chave, valor in dados_escola.items():

            info += "\nE" + str(chave) + " - " + valor[0] + "\n\tAlunos colocados: " + str(valor[1]) + "\n\tVagas sobrantes: " + str(valor[2]) + "\n"

        
        info += u"\n Esta estatística gerou os seguintes ficheiros:\n\n\t- Uma imagem do gráfico com o nome 'grafico.png', relativo ao número de colocações por instituição;\n\n\t- Um ficheiro com extensão '.csv' e com o nome 'colocacoes_inst.csv' que contém os dados da estatística.\n\nOs ficheiros encontram-se na directoria com o caminho:\n\n\t" + os.getcwd()   

        util.criar_csv('colocacoes_inst.csv', dados_escola)    
        self.grafico_colocacoes_instituicao(dados_escola, instituicao)
           
        return info

    def grafico_colocacoes_instituicao(self, dados_escola, instituicao):
        """
        Função que gera um gráfico representativo da estística sobre o número de alunos colocados por instituição;

            Argumentos:
                dados_escola -- dicionário que contém informação sobre o número colocações e o número de vagas sobrantes para cada escola da instituição.
                instituição -- nome da instituição na qual existem as escolas.
        """

        n_grupos = len(dados_escola)    
        n_colocados = []
        n_vagas_sobrantes = []
        xticks = []
        
        for chave, valor in dados_escola.iteritems():
            xticks.append("E" + str(chave))  
            n_colocados.append(valor[1])    
            n_vagas_sobrantes.append(valor[2])

        index = np.arange(n_grupos)
        largura_barras = 0.2
        opacidade = 0.7
        plt.figure(figsize=(8.0, 5.0))
        g1 = plt.bar(index, (n_colocados), largura_barras, color='g', alpha=opacidade)
        g2 = plt.bar(index + largura_barras, (n_vagas_sobrantes), largura_barras, color='r', alpha=opacidade)

        plt.xlabel(u'Escolas', fontsize = 10,  style='italic')
        plt.ylabel(u'Número de colocados', fontsize = 10,  style='italic')
        plt.suptitle(instituicao, fontsize=14, fontweight='bold')
        plt.xticks(index + largura_barras, (xticks), fontsize = 10)
        plt.legend([g1, g2], [u"Número de colocações", u"Número de vagas sobrantes"], loc='lower center', bbox_to_anchor=(0.5, 1), fancybox=True, shadow=True, ncol=2, prop={'size':7})

        plt.savefig('g_colocacoes.png', orientation='portrait')

        return 0

    def percentagem_colocacoes(self, session):
        """
        Função que gera estatísticas relativas à percentagem de alunos colocados por instituição, em relação a todos os alunos colocados na 1ª fase de candidaturas ao ensino superio público português.

            return:
                info -- uma string com a informação resultante das estatísticas.
            
            Argumentos:
                session -- objecto que permite efectuar a ligação a base de dados.
        """
        n_universidades = 0
        n_escolas_institutos = 0
        universidades = {}
        escolas_institutos = {}
        perc_total_universidades = 0
        perc_total_escolas_institutos = 0    
        q_res = session.query(func.sum(bd.EscolaCurso.n_colocados)).all()
        total_CESPN = q_res[0][0]

        q_res = session.query(bd.Instituicao.nome, func.sum(bd.EscolaCurso.n_colocados)).filter(bd.EscolaCurso.id_escola == bd.Escola.id).filter(bd.Escola.id_instituicao == bd.Instituicao.id).group_by(bd.Instituicao.nome).all()

        for res in q_res:
       
            instituicao = util.divide_nome(res[0])

            if instituicao[0] == 'Universidade':
                n_universidades += 1
                perc = (float(res[1]) / total_CESPN) * 100
                perc_total_universidades += perc
                universidades[n_universidades] = (res[0], perc)
            else:
                n_escolas_institutos += 1
                perc = (float(res[1]) / total_CESPN) * 100
                perc_total_escolas_institutos += perc
                escolas_institutos[n_escolas_institutos] = (res[0], perc)
            
            universidades = collections.OrderedDict(sorted(universidades.items()))
            escolas_institutos = collections.OrderedDict(sorted(escolas_institutos.items()))
               
        info = u"Ano Lectivo de 2013/2014 - 1ª Fase das Candidaturas de Acesso ao Ensino Superior Público Nacional\n\nPercentagem de colocações: \n\n\tPercentagem total das colocações em universidades: " + str("%.2f" %perc_total_universidades + "%") + u"\n\n\tPercentagem total das colocações em escolas / institutos: " + str("%.2f" %perc_total_escolas_institutos + "%") + "\n\nDetalhes: \n" 

        for chave, valor in universidades.items():

            info += "\n\tU" + str(chave) + " - " + valor[0] + ":   " + str("%.2f" %valor[1] + "%") + "\n"  

        for chave, valor in escolas_institutos.items():

            info += "\n\tI" + str(chave) + " - " + valor[0] + ":   " + str("%.2f" %valor[1] + "%") + "\n"  

        info += u"\n Esta estatística gerou os seguintes ficheiros:\n\n\t- Uma imagem do gráfico relativo à % de colocações em Universidades, com o nome 'g_universidades.png';\n\n\t- Uma imagem do gráfico relativo à percentagem de % em Escolas ou Institutos, com o nome 'g_escolas_institutos.png';\n\n\t- Um ficheiro com extensão '.csv' e com o nome 'percent_universidades.csv' que contém os dados da estatística relativos às Universidades;\n\n\t- Um ficheiro com extensão '.csv' e com o nome 'percent_escolas_institutos.csv' que contém os dados da estatística relativos às Escolas ou Institutos.\n\nOs ficheiros encontram-se na directoria com o caminho:\n\n\t" + os.getcwd()   

        util.criar_csv('percent_universidades.csv', universidades)
        util.criar_csv('percent_escolas_institutos.csv', escolas_institutos)
        self.grafico_colocacoes_universidades(universidades)
        self.grafico_colocacoes_escolas_institutos(escolas_institutos)
        
        return info

    def grafico_colocacoes_universidades(self, universidades):
        """
        Função que gera um gráfico representativo das estatísticas relativas à percentagem de alunos colocados por instituição sendo estas Universidades, em relação a todos os alunos colocados na 1ª fase de candidaturas ao ensino superio público português.

        Argumentos:
                universidades -- dicionário que contém informação sobre a percentagem de alunos colocados em Universidades, em relação a todos os alunos colocados na 1ª fase de candidaturas ao ensino superio público português.
        """
        n_grupos = len(universidades)    
        percs = []
        xticks = []
        
        for chave, valor in universidades.iteritems():
            xticks.append("U" + str(chave))  
            percs.append(float("%.2f" %valor[1]))    

        index = np.arange(n_grupos)
        largura_barras = 0.4
        opacidade = 0.7

        g_univ = plt.bar(index, (percs), largura_barras, color='c', alpha=opacidade)

        plt.xlabel(u'Universidades', fontsize = 10,  style='italic')
        plt.ylabel(u'% de colocações em relação a todos os alunos colocados', fontsize = 10,  style='italic')
        plt.suptitle(u'Percentagem de colocações em Universidades', fontsize=14, fontweight='bold')
        plt.xticks(index + (float(largura_barras)/2), (xticks), fontsize = 8)
        plt.savefig('g_universidades.png', orientation='portrait')
        plt.close()
    
        return 0

    def grafico_colocacoes_escolas_institutos(self, escolas_institutos):
        """
        Função que gera um gráfico representativo das estatísticas relativas à percentagem de alunos colocados por instituição sendo estas Escolas ou Institutos, em relação a todos os alunos colocados na 1ª fase de candidaturas ao ensino superio público português.

        Argumentos:
                escolas_institutos -- dicionário que contém informação sobre a percentagem de alunos colocados em Escolas ou Institutos, em relação a todos os alunos colocados na 1ª fase de candidaturas ao ensino superio público português.
        """
        n_grupos = len(escolas_institutos)    
        percs = []
        xticks = []
        
        for chave, valor in escolas_institutos.iteritems():
            xticks.append("I" + str(chave))  
            percs.append(float("%.2f" %valor[1]))    

        index = np.arange(n_grupos)
        largura_barras = 0.4
        opacidade = 0.7
    
        g_escolas_institutos = plt.bar(index, (percs), largura_barras, color='y', alpha=opacidade)
    
        plt.xlabel(u'Escolas / Institutos', fontsize = 10,  style='italic')
        plt.ylabel(u'% de colocações em relação a todos os alunos colocados', fontsize = 10,  style='italic')
        plt.suptitle(u'Percentagem de colocações em Escolas / Institutos', fontsize=14, fontweight='bold')
        plt.xticks(index + (float(largura_barras)/2), (xticks), fontsize = 8)
        plt.savefig('g_escolas_institutos.png', orientation='portrait')
        plt.close()
    
        return 0

    def colocacoes_distrito(self, session):
        """
        Função que gera estatísticas relativas ao número de alunos colocados e vagas por colocar por distrito.

            return:
                info -- uma string com a informação resultante das estatísticas.
            
            Argumentos:
                session -- objecto que permite efectuar a ligação a base de dados.
        """
        dados_distritos = {}
        n_distritos = 0
   
        q_res = session.query(bd.Instituicao.distrito, func.sum(bd.EscolaCurso.n_colocados), func.sum(bd.EscolaCurso.vagas_sobrantes)).filter(bd.Escola.id_instituicao == bd.Instituicao.id).filter(bd.EscolaCurso.id_escola == bd.Escola.id).group_by(bd.Instituicao.distrito).all()
   
        for res in q_res:
            n_distritos += 1
            dados_distritos[n_distritos] = (res[0], res[1], res[2])
       
        dados_distritos = collections.OrderedDict(sorted(dados_distritos.items()))

        info = u"Ano Lectivo de 2013/2014 - 1ª Fase das Candidaturas de Acesso ao Ensino Superior Público Nacional - Colocações por Distritos\n\nDistritos: \n"

        for chave, valor in dados_distritos.items():

            info += "\n\tD" + str(chave) + " - " + valor[0] + ":" + "\n\t\tAlunos colocados: " + str(valor[1]) + "\n\t\tVagas sobrantes: " + str(valor[2]) + "\n"

        info += u"\n Esta estatística gerou os seguintes ficheiros:\n\n\t- Uma imagem do gráfico relativo ao número de colocações por distritos, com o nome 'g_colocacoes_distritos.png';\n\n\t- Um ficheiro com extensão '.csv' e com o nome 'colocacoes_distritos.csv' que contém os dados da estatística.\n\nOs ficheiros encontram-se na directoria com o caminho:\n\n\t" + os.getcwd()   

        util.criar_csv('colocacoes_distritos.csv', dados_distritos)
        self.grafico_colocacoes_distrito(dados_distritos)
        
        return info

    def grafico_colocacoes_distrito(self, dados_distritos):
        """
        Função que gera um gráfico representativo das estatísticas relativas ao número de colocações e vagas por colocar por distrito.

        Argumentos:
                dados_distritos -- dicionário que contém informação sobre o número colocações e vagas por colocar por distrito.
        """
        n_grupos = len(dados_distritos)    
        n_colocados = []
        n_vagas_sobrantes = []
        xticks = []

        for chave, valor in dados_distritos.iteritems():
            xticks.append("D" + str(chave))  
            n_colocados.append(valor[1])    
            n_vagas_sobrantes.append(valor[2])
    
        index = np.arange(n_grupos)
        largura_barras = 0.2
        opacidade = 0.7
        plt.figure(figsize=(8.0, 5.0))
        
        g1 = plt.bar(index, (n_colocados), largura_barras, color='g', alpha=opacidade)
        g2 = plt.bar(index + largura_barras, (n_vagas_sobrantes), largura_barras, color='r', alpha=opacidade)
    
        plt.xlabel(u'Distritos', fontsize = 10,  style='italic')
        plt.ylabel(u'Número de colocados', fontsize = 10,  style='italic')
        plt.suptitle(u"Colocações por Distritos", fontsize=14, fontweight='bold')
        plt.xticks(index + largura_barras, (xticks), fontsize = 10)
        plt.legend([g1, g2], [u"Número de colocações", u"Número de vagas sobrantes"], loc='lower center', bbox_to_anchor=(0.5, 1), fancybox=True, shadow=True, ncol=2, prop={'size':7})

        plt.savefig('g_colocacoes_distritos.png', orientation='portrait')

        return 0

    def permilagem_colocacoes_distrito(self, session):
        """
        Função que gera estatísticas relativas à permilagem de alunos colocados por distrito.

            return:
                info -- uma string com a informação resultante das estatísticas.
            
            Argumentos:
                session -- objecto que permite efectuar a ligação a base de dados.
        """
        dados_distritos = {}
        n_distritos = 0
   
        q_res = session.query(bd.Instituicao.distrito, func.sum(bd.EscolaCurso.n_colocados), func.sum(bd.EscolaCurso.vagas_sobrantes)).filter(bd.Escola.id_instituicao == bd.Instituicao.id).filter(bd.EscolaCurso.id_escola == bd.Escola.id).group_by(bd.Instituicao.distrito).all()
   
        for res in q_res:
            n_distritos += 1
            vagas_distrito = res[1] + res[2]
            permilagem = (float(res[1])/vagas_distrito)*1000
            dados_distritos[n_distritos] = (res[0], permilagem)
               
        dados_distritos = collections.OrderedDict(sorted(dados_distritos.items()))
    
        info = u"Ano Lectivo de 2013/2014 - 1ª Fase das Candidaturas de Acesso ao Ensino Superior Público Nacional - Permilagem das Colocações por Distritos\n\nDistritos: \n"
    
        for chave, valor in dados_distritos.items():

            info += "\n\tD" + str(chave) + " - " + valor[0] + ": " + str("%.2f" %valor[1]) + u"‰" + "\n" 

        info += u"\n Esta estatística gerou os seguintes ficheiros:\n\n\t- Uma imagem do gráfico relativo à ‰ de colocações por distritos, com o nome 'g_permil_distritos.png';\n\n\t- Um ficheiro com extensão '.csv' e com o nome 'permil_distritos.csv' que contém os dados da estatística.\n\nOs ficheiros encontram-se na directoria com o caminho:\n\n\t" + os.getcwd()   

        util.criar_csv('permil_distritos.csv', dados_distritos)
        self.grafico_permilagem_colocacoes_distrito(dados_distritos)
        
        return info

    def grafico_permilagem_colocacoes_distrito(self, dados_distritos):
        """
        Função que gera um gráfico representativo da permilagem de colocações por distrito.

            Argumentos:
                dados_distritos -- dicionário que contém informação sobre a permilagem de colocações por distrito.
        """
        n_grupos = len(dados_distritos)    
        permilagem = []
    
        xticks = []
        
        for chave, valor in dados_distritos.iteritems():
            xticks.append("D" + str(chave))  
            permilagem.append(valor[1])    
       
        index = np.arange(n_grupos)
        largura_barras = 0.2
        opacidade = 0.7
        plt.figure(figsize=(8.0, 5.0))
        
        g_permilagem = plt.bar(index, (permilagem), largura_barras, color='g', alpha=opacidade)
   
        plt.xlabel(u'Distritos', fontsize = 10,  style='italic')
        plt.ylabel(u'‰ de colocações por distrito', fontsize = 10,  style='italic')
        plt.suptitle(u"Permilagem de colocações por Distritos", fontsize=14, fontweight='bold')
        plt.xticks(index + largura_barras, (xticks), fontsize = 10)
   
        plt.savefig('g_permil_distritos.png', orientation='portrait')

        return 0

if __name__ == "__main__": main()










